package com.google.code.cisx.client;

import com.google.code.cisx.client.dto.ProjectViewHelper;
import com.google.code.cisx.client.event.EventManager;
import com.google.code.cisx.client.login.LoginEvent;
import com.google.code.cisx.client.login.LoginEventListener;
import com.google.code.cisx.client.login.LoginPanel;
import com.google.code.cisx.client.login.LoginEvent.LoginEventType;
import com.google.code.cisx.client.login.service.LoginService;
import com.google.code.cisx.client.service.RemoteProjectService;
import com.google.code.cisx.client.service.RemoteServiceException;
import com.google.code.cisx.client.session.Session;
import com.google.code.cisx.client.session.SessionTracker;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 * 
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id: CisxDashboard.java 258 2008-11-29 06:23:51Z rahul.thakur.xdev $
 */
public class CisxDashboard implements EntryPoint, HistoryListener, LoginEventListener<LoginEvent> {

  /**
   * Listener attached to the {@link LoginPanel}. This serves as an extension
   * mechanism that allows Client Panels to hook in custom handlers when a Login
   * form is submitted.
   */
  private final LoginPanel.LoginListener loginListener = new LoginPanel.LoginListener() {
    public void onSubmit(final LoginPanel loginPanel) {

      // clear any message on the Login Panel
      loginPanel.setMessage("");
      loginPanel.setErrorMessage("");

      LoginService.Util.getAsyncInstance().login(loginPanel.getUsername(),
          loginPanel.getPassword(), new AsyncCallback() {

            public void onFailure(Throwable caught) {
              loginPanel.setErrorMessage("System error! Please try again later.");
            }

            public void onSuccess(Object result) {
              if (result instanceof String) {
                if (((String) result).equals("Success")) {
                  EventManager.getInstance().dispatchEvent(
                      new LoginEvent(loginPanel, LoginEventType.LOGIN.toString()));
                  loginPanel.setMessage("Login Successful!");
                } else {
                  EventManager.getInstance().dispatchEvent(
                      new LoginEvent(loginPanel, LoginEventType.LOGOUT.toString()));
                  loginPanel.setErrorMessage("Login Failed!");
                }
              }
              // else do nothing
            }
          });
    }
  };

  /**
   * Holder for Login box.
   */
  private final LoginPanel loginPanel = new LoginPanel(loginListener);

  /**
   * Some description text as raw HTML.
   */
  private HTML description = new HTML("<-- Banner Here -->");

  /**
   * This method constructs the application user interface by instantiating
   * controls and hooking up event listeners.
   */
  public void onModuleLoad() {
    setupListeners();
    RootPanel.get("Header").add(description);

    // display login panel only is session was not active
    Session session = SessionTracker.getInstance().getSession();
    if (null == session || !session.isActive()) {
      loginPanel.addStyleName("login");
      DOM.appendChild(RootPanel.get("Content").getElement(), loginPanel.getElement());
      RootPanel.get("Content").add(loginPanel);
      Element navElt = RootPanel.get("Navigation").getElement();
      RootPanel.setVisible(navElt, false);
    }
  }

  /**
   * Register the Dashboard as listener for different types of events.
   */
  private void setupListeners() {
    History.addHistoryListener(this);
    EventManager.getInstance().addEventListener(LoginEventType.LOGIN.toString(), this);
    EventManager.getInstance().addEventListener(LoginEventType.LOGOUT.toString(), this);
    EventManager.getInstance().addEventListener(LoginEventType.TIMEOUT.toString(), this);
  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.gwt.user.client.HistoryListener#onHistoryChanged(java.lang.String)
   */
  public void onHistoryChanged(String historyToken) {
    // TODO Implement!
    Window.alert("Attempting to obtain history for token: " + historyToken
        + " (Not yet implemented). ");

  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.code.cisx.client.event.TypedEventListener#onEvent(com.google.code.cisx.client.event.TypedEvent)
   */
  public void onEvent(LoginEvent event) {
    String type = event.getType();
    if (type.equals(LoginEventType.LOGIN.toString()))
      doLogin(event);
    else if (type.equals(LoginEventType.LOGOUT.toString()))
      doLogout(event);
    else if (type.equals(LoginEventType.TIMEOUT.toString()))
      doTimeout(event);
  }

  /**
   * Does what we need to do when user session times out.
   * 
   * @param event
   */
  private void doTimeout(LoginEvent event) {
    // TODO Implement!
    doLogout(event);
    // TODO: Do some more stuff?
  }

  /**
   * Does what we need to when a user logs out.
   * 
   * @param event
   */
  private void doLogout(LoginEvent event) {
    SessionTracker.getInstance().unbindSession();
    // hide Visual elements/widget which a secured
    Element navElt = RootPanel.get("Navigation").getElement();
    RootPanel.setVisible(navElt, false);

    Element loginElt = this.loginPanel.getElement();
    RootPanel.setVisible(loginElt, true);
  }

  /**
   * Does what we need to do when we login.
   * 
   * @param event
   */
  private void doLogin(LoginEvent event) {
    Session newSession = Session.newSession();
    SessionTracker.getInstance().bindSession(newSession);

    // display Visual elements/widget which a secured
    Element navElt = RootPanel.get("Navigation").getElement();
    RootPanel.setVisible(navElt, true);

    Element loginElt = this.loginPanel.getElement();
    GWT.log("Removing LoginPanel...", null);
    loginPanel.removeFromParent();

    try {
      RemoteProjectService.Util.getAsyncInstance().lookup(100L,
          new AsyncCallback<ProjectViewHelper>() {

            public void onFailure(Throwable caught) {
              Window.alert("Failed to obtain ViewHelper implementation for display.");
            }

            public void onSuccess(ProjectViewHelper result) {
              if (result instanceof ProjectViewHelper) {
                Window.alert("Rendering ProjectViewHelper" + result);

                Window.alert("table rendered!");
              } else {
                RootPanel.get("Content").add(
                    new HTML("<span style='color:red;>No Project found!</span>"));
              }
            }

          });
    } catch (RemoteServiceException e) {
      GWT.log("Error obtaining Project list.", e);
      RootPanel.get("Content").add(
          new HTML("<span style='color:red;>Error occurred obtaining Project list </span>"));
    }
    GWT.log("ProjectListWidget created and rendered.", null);
  }

}
